package task2_2.com.at.count.polsk;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: ATroshanin
 * Date: 01.06.2006
 * Time: 16:07:27
 * To change this template use File | Settings | File Templates.
 */
public class Parser {

    private static final int [][]changeTable = {
                /*digit | znak  |  dot  |letter | space | other*/
    /*0*/       {   1   ,   3   ,   1   ,   2   ,   4   ,  -1   },
    /*number*/  {   1   ,   0   ,   1   ,  -1   ,   4   ,  -1   },
    /*term*/    {   2   ,   0   ,  -1   ,   2   ,   4   ,  -1   },
    /*znak*/    {   0   ,   0   ,   0   ,   0   ,   4   ,  -1   },
    };

    public static synchronized List parse(String expression, Map functions) throws CounterException {

        List result = new ArrayList();

        char []symbols = expression.toCharArray();

        String curentLexem = "";
        int curentSost = 0;
        int sostWas = 0;
        for (int i=0; i<symbols.length; i++) {

            int type = getType(symbols[i]);

            sostWas = curentSost;
            curentSost = changeTable[curentSost][type];
            if (curentSost == -1) {
                throw new CounterException();
                //return null;
            }
            if (curentSost == 0 || curentSost == 4 ) { // ���� ������ ������� ��� ������
                int typeLexem;
                if (sostWas == 1) {
                    typeLexem = Lexeme.TYPE_NUMBER;
                } else if (sostWas == 2) {
                    typeLexem = Lexeme.TYPE_TERM;
                } else if (sostWas == 3) {
                    typeLexem = Lexeme.TYPE_ZNAK;
                } else {
                    curentSost = 0;
                    continue;
                }

                if (functions.get(curentLexem) != null) {
                    typeLexem = Lexeme.TYPE_FUNCTION;
                }

                Lexeme lex = new Lexeme(curentLexem, typeLexem);
                result.add(lex);

                if (curentSost != 4) {
                    curentLexem = "" + symbols[i];
                    curentSost = changeTable[curentSost][type];
                } else {
                    curentLexem = "";
                    curentSost = 0;
                }

            } else {
                curentLexem = curentLexem + symbols[i];
            }

        }

        if (curentLexem.length() >0) {
            int typeLexem;
            if (curentSost == 1) {
                typeLexem = Lexeme.TYPE_NUMBER;
            } else if (curentSost == 2) {
                typeLexem = Lexeme.TYPE_TERM;
            } else if (curentSost == 3) {
                typeLexem = Lexeme.TYPE_ZNAK;
            } else {
                // TODO ERR here!!!
                typeLexem = -1;
            }
            Lexeme lex = new Lexeme(curentLexem, typeLexem);
            result.add(lex);
        }

        return result;
    }

    private static int getType(char sym) {

        if (sym >= 48 && sym <=57) {
            return 0;
        } else if (sym == '+' || sym == '-' || sym == '*' || sym == '/' || sym == '(' || sym == ')') {
            return 1;
        } else if (sym == '.'){
            return 2;
        } else if ((sym >= 'a' && sym < 'z') || (sym >= 'A' && sym < 'Z')){
            return 3;
        } else if (sym == ' '){
            return 4;
        } else {
            return 5;
        }
    }

}
